﻿using System.Collections.Generic;
using System.Linq;
using Kooboo.CMS.Content.Models;
using Kooboo.CMS.Content.Query;
using Kooboo.CMS.Content.Services;
using System.Collections.Specialized;
using System.Web;

namespace KB.Bizs
{
    public abstract class BizBase<TEntity>
      where TEntity : TextContent
    {
        private Repository _currentRepository = Repository.Current;
        public Repository CurrentRepository
        {
            set { _currentRepository = value; }
            get
            {
                return _currentRepository;
            }
        }

        private string _folderName;

        public virtual string FolderName
        {
            get
            {
                if (string.IsNullOrEmpty(_folderName))
                {
                    _folderName = typeof(TEntity).Name;
                }

                return _folderName;
            }
        }

        private string _categoryName;
        public virtual string CategoryName
        {
            get
            {
                if (string.IsNullOrEmpty(_categoryName))
                {
                    _categoryName = FolderName + "Category";
                }

                return _categoryName;
            }
        }
        private TextFolder _folder;
        public TextFolder Folder
        {
            get
            {
                if (_folder == null)
                {
                    _folder = new TextFolder(CurrentRepository, FolderName).AsActual();
                }

                return _folder;
            }
        }

        private TextFolder _categoryfolder;
        public TextFolder CategoryFolder
        {
            get
            {
                if (_categoryfolder == null)
                {
                    _categoryfolder = new TextFolder(CurrentRepository, FolderName).AsActual();
                }

                return _categoryfolder;
            }
        }

        public abstract TEntity Get(TextContent content);

        public TEntity Get(ContentBase content)
        {
            if (content != null)
            {
                var textContent = new TextContent(content);
                return Get(textContent);
            }

            return null;
        }

        public IContentQuery<TextContent> QueryAll()
        {
            return Folder.CreateQuery();
        }

        #region Query

        public IContentQuery<TextContent> Query(bool onlyPublished = true)
        {
            var list = QueryAll();
            return onlyPublished ? list.Published() : list;
        }

        public IContentQuery<TextContent> Query(string fieldName, object fieldValue, bool onlyPublished = true)
        {
            return Query(onlyPublished).WhereEquals(fieldName, fieldValue);
        }

        public IContentQuery<TextContent> Query(string uuid, bool onlyPublished = true)
        {
            return Query(KEY.TextContents.UUID, uuid, onlyPublished);
        }

        public IContentQuery<TextContent> QueryOrdered(int top = 0, bool onlyPublished = true)
        {
            var list = Query(onlyPublished).OrderBy(Folder);
            return top > 0 ? list.Take(top) : list;
        }

        public IContentQuery<TextContent> QueryByParentUUID(string parentUUID, bool onlyPublished = true)
        {
            return Query(KEY.TextContents.ParentUUID, parentUUID, onlyPublished);
        }

        public IContentQuery<TextContent> QueryByCategoryUUID(string uuid, bool onlyPublished = true)
        {
            return Query(onlyPublished).WhereCategory(CategoryFolder.CreateQuery().WhereEquals(KEY.TextContents.UUID, uuid));
        }

        public IContentQuery<TextContent> QueryByCategoryUUIDs(string[] uuid, bool onlyPublished = true)
        {
            return Query(onlyPublished).WhereCategory(CategoryFolder.CreateQuery().WhereIn(KEY.TextContents.UUID, uuid));
        }

        public TEntity Get(string fieldName, object fieldValue, bool onlyPublished = true)
        {
            return Get(Query(fieldName, fieldValue, onlyPublished).FirstOrDefault());
        }
        public TEntity Get(string uuid, bool onlyPublished = true)
        {
            return Get(KEY.TextContents.UUID, uuid, onlyPublished);
        }
        public TEntity GetByUserKey(string userkey, bool onlyPublished = true)
        {
            return Get(KEY.TextContents.UserKey, userkey, onlyPublished);
        }

        public IEnumerable<TEntity> GetList(bool onlyPublished = true)
        {
            return Query(onlyPublished).Select(it => Get(it));
        }
        public IEnumerable<TEntity> GetList(string fieldName, object fieldValue, bool onlyPublished = true)
        {
            return Query(fieldName, fieldValue, onlyPublished).Select(it => Get(it));
        }

        public IEnumerable<TEntity> GetListOrdered(int top = 0, bool onlyPublished = true)
        {
            return QueryOrdered(top,onlyPublished).Select(it => Get(it));
        }

        #endregion

        #region CUD

        #region Add

        public TEntity Add(TEntity T, IEnumerable<TextContent> categories = null, HttpFileCollectionBase files = null, string userName = "")
        {
            var content = ServiceFactory.TextContentManager.Add(
                    CurrentRepository,
                    Folder,
                    T.ParentFolder,
                    T.ParentUUID,
                    T.ToNameValueCollection(),
                    files,
                    categories,
                    userName
                );
            return Get(content);
        }

        public TEntity Add(TEntity T, string[] categoryUUIDs, string userName = "")
        {
            var categoryQuery = CategoryFolder.CreateQuery();
            IEnumerable<TextContent> categories = null;
            foreach (var categoryUUID in categoryUUIDs)
            {
                categories = categoryQuery.WhereIn(KEY.TextContents.UUID, categoryUUIDs);
            }
            return Add(T, categories, null, userName);
        }

        public TEntity Add(NameValueCollection values, IEnumerable<TextContent> categories = null, HttpFileCollectionBase files = null, string userName = "")
        {
            var content = ServiceFactory.TextContentManager.Add(CurrentRepository, Folder, values, files, categories, userName);
            return Get(content);
        }

        #endregion

        #region Update

        public TEntity Update(TEntity T, string userName = "")
        {
            var content = ServiceFactory.TextContentManager.Update(
                    CurrentRepository,
                    Folder.GetSchema(),
                    T.UUID,
                    T.ToNameValueCollection(),
                    null,
                    userName);

            return Get(content);
        }

        public void Update(string uuid, IEnumerable<string> fieldNames, IEnumerable<object> fieldValues, string userName = "")
        {
            ServiceFactory.TextContentManager.Update(
                CurrentRepository,
                Folder.GetSchema(),
                uuid,
                fieldNames,
                fieldValues,
                userName);
        }
        public void Update(string uuid, string fieldName, object fieldValue, string userName = "")
        {
            ServiceFactory.TextContentManager.Update
                (CurrentRepository,
                Folder.GetSchema(),
                uuid,
                fieldName,
                fieldValue,
                userName);
        }

        public TEntity Update(string uuid, NameValueCollection values, string userName = "")
        {
            var content = ServiceFactory.TextContentManager.Update(
                  CurrentRepository,
                  Folder.GetSchema(),
                  uuid,
                  values,
                  null,
                  userName);
            return Get(content);
        }

        #endregion

        #region Delete

        public void Delete(string uuid)
        {
            ServiceFactory.TextContentManager.Delete(
                 CurrentRepository,
                 Folder.GetSchema(),
                 uuid);
        }

        #endregion

        #endregion
    }
}
